package com.snail.mobile.sim.oss.util;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;

import org.apache.commons.lang.time.DateFormatUtils;



public class DateUtils {
	public static final String DATE_YMD = "yyyy-MM-dd";
	public static final String DATE_MD = "yy-MM-dd";
	public static final String DATE_YMD_I = "yyyy/MM/dd";
	public static final String DATE_YM = "yyyy-MM";
	public static final String DATE_Y = "yyyy";
	public static final String DATE_YMD_HMS = "yyyy-MM-dd HH:mm:ss";
	public static final String DATE_YMD_HM = "yyyy-MM-dd HH:mm";
	public static final String DATE_YMD_H = "yyyy-MM-dd HH";
	public static final String DATE_HMS = "HH:mm:ss";
	public static final String DATE_YMDHMS = "yyyyMMddHHmmss";
	public static final String DATE_YMD_C = "yyyyMMdd";
	public static final String DATE_YHD_HMSS = "yyyy-MM-dd HH:mm:ss:SSS";

	// 限制实例化

	private DateUtils() {}

	/**
	 * String -> Date，使用默认的日期格式{@link #DATE_YMD_HMS}解析
	 * 
	 * @param strDate
	 *            ，strDate 待解析的字符串
	 * @return Date对象
	 */
	public static Date parseDate(String strDate) {
		return parseDate(strDate, null);
	}
	
	/**
	 * Timestamp -> String
	 * 
	 * @param time
	 * @return
	 */
	public static String parseTime(Timestamp time) {
		return new SimpleDateFormat(DATE_YMD_HMS).format(time);
	}

	/**
	 * Date -> String ，转换数据库date字段用
	 * 
	 * @param dateStr
	 *            日期字符串
	 * @param strFomate
	 *            格式
	 * @return 所需结果
	 */
	public static String dateToStringFormat(String dateStr, String strFomate) {
		return dateToString(stringToDate(dateStr, strFomate), strFomate);
	}

	/**
	 * String -> Date
	 * 
	 * @param strDate
	 *            待解析的字符串
	 * @param strFomate
	 *            格式
	 * @return Date对象
	 */
	public static Date parseDate(String strDate, String strFomate) {
		if (strFomate == null) strFomate = DATE_YMD_HMS;
		SimpleDateFormat df = new SimpleDateFormat(strFomate);

		return df.parse(strDate, new ParsePosition(0));
	}

	/**
	 * String -> String格式化
	 * 
	 * @param strDate
	 *            待解析的字符串
	 * @param strFomate
	 *            格式
	 * @return Date对象
	 */
	public static String parseStringDate(String strDate, String strFomate) {
		if (strFomate == null) strFomate = DATE_YMD_HMS;
		SimpleDateFormat df = new SimpleDateFormat(strFomate);
		Date date = df.parse(strDate, new ParsePosition(0));
		return dateToString(date, strFomate);
	}

	/**
	 * Timestamp -> String格式化
	 * 
	 * @param ts
	 *            待解析的字符串
	 * @param strFomate
	 *            格式
	 * @return Date对象
	 */
	public static String parseStringDate(Timestamp ts, String strFomate) {
		if (ts == null) return "";
		if (strFomate == null) strFomate = DATE_YMD_HMS;
		SimpleDateFormat df = new SimpleDateFormat(strFomate);
		Date date = df.parse(df.format(ts), new ParsePosition(0));
		return dateToString(date, strFomate);
	}

	/**
	 * 获得昨天的日期
	 * 
	 * @return 昨天的日期，格式为{@link #DATE_YMD}
	 */
	public static String getYesterday() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, -1);

		return DateFormatUtils.format(cal.getTime(), DATE_YMD);
	}

	/**
	 * 获得"以今天为基准"的前几天的日期，或者后几天的日期，格式为{@link #DATE_YMD}
	 * 
	 * @param num
	 *            所要日期与当前日期的相差数,当num为正数时，指后num天的日期，当num为负数时，指前几天的日期
	 * @return 所要结果
	 */
	public static String getDayLessOrMore(int num) {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, num);

		return DateFormatUtils.format(cal.getTime(), DATE_YMD);
	}

	/**
	 * 获得"以某天为基准"的前几天的日期，或者后几天的日期，格式为{@link #DATE_YMD}
	 * 
	 * @param time
	 *            时间
	 * @param num
	 *            所要日期与当前日期的相差数,当num为正数时，指后num天的日期，当num为负数时，指前几天的日期
	 * @return 所要结果
	 */
	public static String getDayLessOrMore(String time, int num) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(DateUtils.parseDate(time, DATE_YMD));
		cal.add(Calendar.DATE, num);

		return DateFormatUtils.format(cal.getTime(), DATE_YMD);
	}

	/**
	 * 获得指定日期的前一天日期，时间格式为"yyyy-MM-dd"
	 * 
	 * @param time
	 *            指定时间
	 * @return 所需结果
	 */
	public static String getYesterday(String time) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(DateUtils.parseDate(time, DATE_YMD));
		cal.add(Calendar.DATE, -1);

		return DateFormatUtils.format(cal.getTime(), DATE_YMD);
	}

	/**
	 * 获得当前时间，格式为"yyyyMMddhhmmss"，精确到秒
	 * 
	 * @param strFomate
	 *            格式
	 * @return 所需时间
	 */

	public static String getTodayTime(String strFomate) {
		return DateFormatUtils.format(new Date(), strFomate);

	}

	/**
	 * 获得当前时间, 格式为"yyyyMMddhhmmssSS"，精确到毫秒
	 * 
	 * @param strFomate
	 *            格式
	 * @return 所需时间
	 */

	public static String getTodayTimeMS(String strFomate) {
		return DateFormatUtils.format(new Date(), strFomate);

	}

	/**
	 * 获得当前时间，格式为"yyyy-MM-dd HH:mm:ss"，精确到秒
	 * 
	 * @return 所需结果
	 */

	public static String getTodayTimeS() {
		return DateFormatUtils.format(new Date(), DATE_YMD_HMS);

	}

	/**
	 * 日期转为字符
	 * 
	 * @param date
	 *            yyyy-mm-dd
	 * @return
	 */
	public static Date stringToDate(String date) {
		if (date != null) {
			try {
				SimpleDateFormat sdf = new SimpleDateFormat(DATE_YMD);
				return sdf.parse(date);
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
		return new Date();
	}

	/**
	 * 日期转为字符
	 * 
	 * @param date
	 *            String日期
	 * @param strFomate
	 *            格式
	 * @return 转换后的日期
	 */
	public static Date stringToDate(String date, String strFomate) {
		if (strFomate == null) strFomate = DATE_YMD_HMS;
		if (date != null) {
			try {
				SimpleDateFormat sdf = new SimpleDateFormat(strFomate);
				return sdf.parse(date);
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
		return new Date();
	}

	/**
	 * @return 今天的日期，格式为{@link #DATE_YMD}
	 */
	public static String getToday() {
		return DateFormatUtils.format(new Date(), DATE_YMD);
	}

	/**
	 * Date -> String ，使用默认的日期格式{@link #DATE_YMD_HMS}解析
	 * 
	 * @param strFomate
	 *            格式
	 * @param date
	 *            对象
	 * @return 所需结果
	 */
	public static String dateToString(Date date, String strFomate) {
		if (strFomate == null) strFomate = DATE_YMD_HMS;
		SimpleDateFormat sdf = new SimpleDateFormat(strFomate);
		return sdf.format(date);
	}

	/**
	 * 获得前/后m分钟的时间
	 * 
	 * @param m
	 *            负数:前m分钟;正数:后m分钟;
	 * @return 所需结果
	 */
	public static String getBeforeMinute(int m) {
		SimpleDateFormat format = new SimpleDateFormat(DATE_YMD_HMS);

		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MINUTE, m);

		return format.format(calendar.getTime());
	}

	/**
	 * 时间差
	 * 
	 * @param startTime
	 *            开始时间
	 * @param endTime
	 *            结束时间
	 * @return 返回时间差数组:(天,时:分:秒)
	 */
	public static Object[] timeDifference(Date startTime, Date endTime) {
		if (startTime == null || endTime == null) {
			return new Object[] { 0, 0, 0, 0 };
		} else {
			Calendar start = Calendar.getInstance();
			Calendar end = Calendar.getInstance();
			start.setTime(startTime);
			end.setTime(endTime);
			long startMs = start.getTimeInMillis();
			long endMs = end.getTimeInMillis();
			long l_differ = endMs - startMs;// 毫秒数
			long s_differ = l_differ / 1000;// 秒
			long ll_differ = l_differ / 1000;// 秒
			long d_differ = s_differ / (60 * 60 * 24);// 得到天数
			s_differ = s_differ - d_differ * 60 * 60 * 24;// 天
			long h_differ = s_differ / (60 * 60);// 时
			s_differ = s_differ - h_differ * 60 * 60;
			long m_differ = s_differ / 60;// 分
			s_differ = s_differ - m_differ * 60;

			return new Object[] { d_differ, h_differ, m_differ, s_differ, ll_differ, ll_differ / 60 };
		}
	}

	/**
	 * 要转换的毫秒数
	 * 
	 * @param mss
	 *            要转换的毫秒数
	 * @return 该毫秒数转换为 * days * hours * minutes 后的格式
	 */
	public static String formatDuring(long mss) {
		long days = mss / (1000 * 60 * 60 * 24);
		long hours = (mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
		long minutes = (mss % (1000 * 60 * 60)) / (1000 * 60);
		// long seconds = (mss % (1000 * 60)) / 1000;

		StringBuilder builder = new StringBuilder();
		if (days != 0) {
			builder.append(days);
			builder.append(" 天 ");
		}
		if (hours != 0) {
			builder.append(hours);
			builder.append(" 小时 ");
		}
		if (minutes != 0) {
			builder.append(minutes);
			builder.append(" 分钟");
		}
		return builder.toString();
	}

	/**
	 * 格式化日期
	 * 
	 * @param date
	 *            日期
	 * @return 格式化结果
	 */
	public static String format(Date date) {
		return format(date, DATE_YMD_HMS);
	}

	/**
	 * 格式化日期
	 * 
	 * @param date
	 *            日期
	 * @param strFormat
	 *            日期格式
	 * @return 格式化结果
	 */
	public static String format(Date date, String strFormat) {
		DateFormat format = new SimpleDateFormat(strFormat);
		return format.format(date);
	}

	/**
	 * 获取当前系统时间 Timestamp 格式
	 * 
	 * @return 当前系统时间
	 */
	public static Timestamp getNowTimestamp() {
		return new Timestamp(System.currentTimeMillis());
	}

	/**
	 * String 转 Timestamp 格式
	 * 
	 * @param timestamp
	 *            String格式的时间
	 * @param strFormat
	 *            日期格式
	 * @return 格式化结果
	 */
	public static Timestamp stringToTimestamp(String timestamp, String strFormat) {
		SimpleDateFormat df = new SimpleDateFormat(strFormat);
		String time = df.format(parseDate(timestamp));
		return Timestamp.valueOf(time);
	}

	/**
	 * String 转 Timestamp 格式
	 * 
	 * @param timestamp
	 *            String格式的时间
	 * @return 格式化结果
	 */
	public static Timestamp stringToTimestamp(String timestamp) {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String time = df.format(parseDate(timestamp));
		return Timestamp.valueOf(time);
	}

	/**
	 * String 转 Timestamp 格式
	 * 
	 * @param timestamp
	 *            String格式的时间
	 * @return 格式化结果
	 */
	public static Timestamp stringToTimestampMS(String timestamp) {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
		String time = df.format(parseDate(timestamp));
		return Timestamp.valueOf(time);
	}

	/**
	 * 日期转为毫秒
	 * 
	 * @param date
	 *            日期
	 * @return 结果
	 */
	public static Long dateToMillisecond(String date) {
		SimpleDateFormat simpledateformat = new SimpleDateFormat(DATE_YMD, Locale.SIMPLIFIED_CHINESE);
		Date date2 = null;
		try {
			date2 = simpledateformat.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		assert date2 != null;
		return date2.getTime();
	}

	/**
	 * 日期转为毫秒
	 * 
	 * @param date
	 *            日期
	 * @return 结果
	 */
	public static Long dateToMilli(String date) {
		SimpleDateFormat simpledateformat = new SimpleDateFormat(DATE_YMD_HMS, Locale.SIMPLIFIED_CHINESE);
		Date date2 = null;
		try {
			date2 = simpledateformat.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		assert date2 != null;
		return date2.getTime();
	}

	/**
	 * 获取日期中的小时
	 * 
	 * @param date
	 *            日期
	 * @param cale
	 *            类型
	 * @return 获取的值
	 */
	public static Integer getCalendar(Date date, int cale) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		return calendar.get(cale);
	}

	/**
	 * 取得两个日期之间的所有日期
	 * 
	 * @param begin
	 *            开始日期
	 * @param end
	 *            结束日期
	 * @return 日期集合
	 */
	public static String[] getBetweenDate(String begin, String end) {
		List<String> lDate = new ArrayList<String>();
		lDate.add(begin.replace("-", "/"));
		Calendar cal = Calendar.getInstance();
		// 使用给定的 Date 设置此 Calendar 的时间
		cal.setTime(stringToDate(begin));

		boolean tmp = true;
		while (tmp) {
			// 根据日历的规则，为给定的日历字段添加或减去指定的时间量
			cal.add(Calendar.DAY_OF_MONTH, 1);
			// 测试此日期是否在指定日期之后
			if (stringToDate(end).after(cal.getTime())) {
				// 根据日历的规则，为给定的日历字段添加或减去指定的时间量
				lDate.add(dateToString(cal.getTime(), DATE_YMD_I));
			} else {
				tmp = false;
			}
		}
		if (!begin.equals(end)) {
			lDate.add(end.replace("-", "/"));
		}
		return lDate.toArray(new String[lDate.size()]);
	}

	/**
	 * 获得指定日期的前一天日期，时间格式为"yyyy-MM-dd"
	 * 
	 * @param time
	 *            指定时间
	 * @param num
	 *            增加或者减少日期天数(-1:一天以前)
	 * @return 所需结果
	 */
	public static String getBeforeToday(String time, Integer num) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(DateUtils.parseDate(time, DATE_YMD));
		cal.add(Calendar.DATE, num);

		return DateFormatUtils.format(cal.getTime(), DATE_YMD);
	}

	/**
	 * 获取日期的小时
	 * 
	 * @param date
	 *            日期
	 * @return 结果
	 */
	public static int getDateForHour(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(Calendar.HOUR_OF_DAY);
	}

	/**
	 * 获取日期的日期
	 * 
	 * @param date
	 *            日期
	 * @return 结果
	 */
	public static int getDateForDay(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(Calendar.DATE);
	}
	/**
	 * 获取日期的日期
	 * 
	 * @param date
	 *            日期
	 * @return 结果
	 */
	public static int getMonthForDay(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(Calendar.DATE);
	}

	/**
	 * 获取日期的分钟
	 * 
	 * @param date
	 *            日期
	 * @return 结果
	 */
	public static int getDateForMinute(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(Calendar.MINUTE);
	}

	/**
	 * 获取前日的最小时间和最大时间
	 * 
	 * @param bool
	 *            判断值
	 * @return 结果
	 */
	public static Timestamp getYesterdayByMinAndMax(Boolean bool) {
		String today = getYesterday();
		if (bool) {
			return DateUtils.stringToTimestamp(today + " 00:00:00");
		} else {
			return DateUtils.stringToTimestamp(today + " 23:59:59");
		}
	}

	public static Date getFirstDayOfWeek(int year, int week) {
		Calendar calFirst = Calendar.getInstance();
		calFirst.set(year, 0, 7);
		Date firstDate = getFirstDayOfWeek(calFirst.getTime());

		Calendar firstDateCal = Calendar.getInstance();
		firstDateCal.setTime(firstDate);

		Calendar c = new GregorianCalendar();
		c.set(Calendar.YEAR, year);
		c.set(Calendar.MONTH, Calendar.JANUARY);
		c.set(Calendar.DATE, firstDateCal.get(Calendar.DATE));

		Calendar cal = (GregorianCalendar) c.clone();
		cal.add(Calendar.DATE, (week - 1) + 7);
		firstDate = getFirstDayOfWeek(cal.getTime());
		return firstDate;
	}

	/**
	 * 取得当前日期所在周的第一天
	 * 
	 * @param date
	 *            当前日期
	 * @return 所在周的第一天
	 */
	public static Date getFirstDayOfWeek(Date date) {
		Calendar cc = new GregorianCalendar();
		cc.setFirstDayOfWeek(Calendar.MONDAY);
		cc.setTime(date);
		cc.set(Calendar.DAY_OF_WEEK, cc.getFirstDayOfWeek());
		return cc.getTime();
	}

	/**
	 * 根据日期得到所在年度的周次
	 * 
	 * @param date
	 *            日期
	 * @return 周次
	 */
	public static String getWeekByDate(Date date) {
		Calendar c = new GregorianCalendar();
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.setMinimalDaysInFirstWeek(7);
		c.setTime(date);
		String week = Integer.toString(c.get(Calendar.WEEK_OF_YEAR));
		if (week.length() == 1) week = "0" + week;
		String year = Integer.toString(c.get(Calendar.YEAR));
		return year + "-" + week;
	}

	/**
	 * 获取当前月份
	 * 
	 * @return 月份(整型)
	 */
	public static int getCurrentMonth() {
		Calendar c = Calendar.getInstance(Locale.CHINA);
		return c.get(Calendar.MONTH) + 1;
	}

	/**
	 * 获取指定月份的前后几月的第一天
	 * 
	 * @param date
	 *            指定日期
	 * @param month
	 *            指定月份,负数代表以当前月份以前的月份
	 * @return 指定月份的第一天日期
	 */
	public static Date getFirstDayOfSomeMonth(String date, int month) {
		Calendar c = Calendar.getInstance(Locale.CHINA);
		c.setTime(DateUtils.parseDate(date, DATE_YMD));
		c.add(Calendar.MONTH, month);
		c.set(Calendar.DAY_OF_MONTH, 1);
		return c.getTime();
	}

	/**
	 * 获取指定日期前后周的第一天
	 * 
	 * @param date
	 *            指定日期
	 * @param week
	 *            指定周,负数代表以当前周以前的周
	 * @return 指定日期前后周的第一天日期
	 */
	public static Date getFirstDayOfSomeWeek(String date, int week) {
		Calendar c = Calendar.getInstance(Locale.CHINA);
		c.setTime(DateUtils.parseDate(date, DATE_YMD));
		c.add(Calendar.WEEK_OF_YEAR, week);
		c.set(Calendar.DAY_OF_WEEK, 2); // 从周一开始
		return c.getTime();
	}

	/**
	 * 获取Long型日期数据
	 * 
	 * @param date
	 *            日期
	 * @return Long型日期数据
	 */
	public static Long getLongDate(String date) {
		try {
			SimpleDateFormat sf = new SimpleDateFormat(DATE_YMD_HMS);
			return sf.parse(date).getTime();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 定义时间类型常量
	 */
	private final static int SECOND = 1;
	private final static int MINUTE = 2;
	private final static int HOUR = 3;
	private final static int DAY = 4;

	/**
	 * 将一个表示时间段的数转换为毫秒数
	 * 
	 * @param num
	 *            时间差数值,支持小数
	 * @param type
	 *            时间类型：1->秒,2->分钟,3->小时,4->天
	 * @return long类型时间差毫秒数，当为-1时表示参数有错
	 */
	public static long formatToTimeMillis(double num, int type) {
		if (num <= 0) return 0;
		switch (type) {
			case SECOND:
				return (long) (num * 1000);
			case MINUTE:
				return (long) (num * 60 * 1000);
			case HOUR:
				return (long) (num * 60 * 60 * 1000);
			case DAY:
				return (long) (num * 24 * 60 * 60 * 1000);
			default:
				return -1;
		}
	}

	/**
	 * 获取某一指定时间的前一段时间
	 * 
	 * @param num
	 *            时间差数值
	 * @param type
	 *            时间差类型：1->秒,2->分钟,3->小时,4->天
	 * @param date
	 *            参考时间
	 * @return 返回格式化时间字符串
	 */
	public static String getPreTimeStr(double num, int type, Date date) {
		long nowLong = date.getTime();// 将参考日期转换为毫秒时间
		Date time = new Date(nowLong - formatToTimeMillis(num, type));// 减去时间差毫秒数
		return getTimeByDate(time);
	}

	/**
	 * 获取某一指定时间的前一段时间
	 * 
	 * @param num
	 *            时间差数值
	 * @param type
	 *            时间差类型：1->秒,2->分钟,3->小时,4->天
	 * @param date
	 *            参考时间
	 * @return 返回Date对象
	 */
	public static Date getPreTime(double num, int type, Date date) {
		long nowLong = date.getTime();// 将参考日期转换为毫秒时间
		Date time = new Date(nowLong - formatToTimeMillis(num, type));// 减去时间差毫秒数
		return time;
	}

	/**
	 * 获取某一指定时间的后一段时间
	 * 
	 * @param num
	 *            时间差数值
	 * @param type
	 *            时间差类型：1->秒,2->分钟,3->小时,4->天
	 * @param date
	 *            参考时间
	 * @return 返回格式化时间字符串
	 */
	public static String getNextTimeStr(double num, int type, Date date) {
		long nowLong = date.getTime();// 将参考日期转换为毫秒时间
		Date time = new Date(nowLong + formatToTimeMillis(num, type));// 加上时间差毫秒数
		return getTimeByDate(time);
	}

	/**
	 * 获取某一指定时间的后一段时间
	 * 
	 * @param num
	 *            时间差数值
	 * @param type
	 *            时间差类型：1->秒,2->分钟,3->小时,4->天
	 * @param date
	 *            参考时间
	 * @return 返回Date对象
	 */
	public static Date getNextTime(double num, int type, Date date) {
		long nowLong = date.getTime();// 将参考日期转换为毫秒时间
		Date time = new Date(nowLong + formatToTimeMillis(num, type));// 加上时间差毫秒数
		return time;
	}
	
	public static int getCalendar(int calendar){
		Calendar cal = Calendar.getInstance();
		return cal.get(calendar);
	}
	 

	/**
	 * 得到一个日期函数的格式化时间
	 * 
	 * @param date
	 *            日期对象
	 * @return
	 */
	public static String getTimeByDate(Date date) {
		return DateFormatUtils.format(new Date(), DATE_YMD_HMS);
	}
}
